from io import BytesIO
import json
from pathlib import Path
from urllib import request
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import ListView, CreateView, UpdateView, DeleteView, DetailView
from django.db import models
import openpyxl

from grades.models import Grade
from scores.forms import ScoreForm
from scores.models import Score
from students.models import Student
from utils.handle_excel import ReadExcel

# Create your views here.
class BasecoreView():
    model = Score # 指定模型
    form_class = ScoreForm  # 关键：指定表单类
    success_url = reverse_lazy('score_list')
    context_object_name = 'scores'
    
class ScoresListView(BasecoreView, ListView):
    template_name = 'scores/score_list.html' # 指定模板
    # context_object_name = 'scores'
    paginate_by = 10    

    def get_queryset(self):
        queryset = super().get_queryset()
        grade_id = self.request.GET.get('grade')
        search = self.request.GET.get('search')
        
        if grade_id:
            queryset = queryset.filter(grade__pk=grade_id)
            
        if search:
            queryset = queryset.filter(
                models.Q(student_name__icontains=search) |
                models.Q(student_number__icontains                                                                                                                                  =search)
            )
        # 外键关系访问Grade模型的grade_number字段
        queryset = queryset.order_by('grade__grade_number', 'student_number')
        return queryset
    
    def get_context_data(self, **kwargs):
        context = super(ScoresListView, self).get_context_data(**kwargs)
        # 获取所有班级并添加到上下文
        context['grades'] = Grade.objects.all().order_by('grade_number')
        context['current_grade'] = self.request.GET.get('grade', '') 
        return context
    

class ScoresCreateView(BasecoreView, CreateView):
    # form_class = ScoreForm
    template_name = 'scores/score_form.html'

    def form_valid(self, form):
        student_name = form.cleaned_data.get('student_name')
        student_number = form.cleaned_data.get('student_number')
        grade_id = form.cleaned_data.get('grade')

        try:
            student = Student.objects.get(student_name=student_name, student_number=student_number, grade_id=grade_id)
        except Student.DoesNotExist:
            errors = {'general': [{'message':'学生信息不存在', 'code':'not_found'}]}
            return JsonResponse({'status':'error', 'messages':errors}, status=404)

        form.save()
        return JsonResponse({'status': 'success', 'messages': '添加成功'}, status=200)
    
    def form_invalid(self, form):
        errors = form.errors.as_json() #获取所有错误信息
        return JsonResponse({'status': 'error','messages':errors,}, status=400)
        # 验证失败


class ScoresUpdateView(BasecoreView, UpdateView):
    template_name = 'scores/score_form.html'

    def form_valid(self, form):
        form.save()

        return JsonResponse({'status':'success','messages':'更新成功'}, status=200)
    
    def form_invalid(self, form):
        errors = form.errors.as_json() # 获取所有错误信息
        return JsonResponse({'status': 'error','messages':errors}, status=400)

    
class ScoresDeleteView(BasecoreView, DeleteView):

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        # response = super().delete(request, *args, **kwargs)
        try:
            self.object.delete()
            return JsonResponse({'status':'success','messages':'删除成功',},status=200)
        except Exception as e:
            return JsonResponse({'status': 'error','messages':'删除失败' + str(e)},status=400)


class ScoresBulkDelteView(BasecoreView, DeleteView):
    
    def post(self, request, *args, **kwargs):
        # return super().post(request, *args, **kwargs)
        print('执行post操作')
        select_ids = request.POST.getlist('score_ids')

        if not select_ids:
            return JsonResponse({'status':'error', 'messages':'请选择要删除的成绩'}, status=500)
        print('获取选中的id')
        try:
            self.object_list = self.get_queryset().filter(id__in=select_ids)
            self.object_list.delete()
            return JsonResponse({'status':'success','messages':'删除成功',}, status=200)
        except Exception as e:
            print(e)
            return 
        

def upload_scores(request):
    """上传学生成绩信息"""
    if request.method == 'POST':
        file = request.FILES['excel_file']

        if not file:
            return JsonResponse({'status': 'error','messages': '请上传excel文件',}, status=400)
        
        ext = Path(file.name).suffix 
        if ext.lower() != '.xlsx':
            return JsonResponse({'status': 'error','messages': '文件类型错误，请上传.xlsx格式的文件'}, status=400)

        # openpyxl 读取excel文件内容
        read_excel = ReadExcel(file)
        data = read_excel.get_data()
        if data[0] !=  ['考试名称','姓名','班级','学号','语文','数学','英语']:
            return JsonResponse({'status': 'error','messages': '信息内容有误',}, status=400)

        # 写入到数据库
        for row in data[1:]:
            title, student_name, grade, student_number,chinese_score, math_score, english_score = row
            grade = Grade.objects.filter(grade_name=grade).first()
            if not grade:
                return JsonResponse({'status': 'error','messages': f'{grade}不存在',
                }, status=400)
            
            if not student_name:
                return JsonResponse({'status':'error', 'messages':'学生姓名不为空'}, status=400)
            
            # 检查学生成绩是否存在
            if Score.objects.filter(title=title, student_number=student_number).exists():
                return JsonResponse({'status':'error', 'messages':f'【学号:{student_number}的{title}】成绩信息已存在'}, status=400)

            try:
                Score.objects.create(
                    title = title,
                    student_name = student_name,
                    grade = grade,
                    student_number = student_number,
                    chinese_score = chinese_score,
                    math_score = math_score,
                    english_score = english_score,
                )
            except Exception as e:
                return JsonResponse({'status':'error', 'messages':f'上传失败{e}'}, status=500)
            
        return JsonResponse({'status':'success', 'messages':'上传成功'}, status=200)


def export_scores(request):
    if request.method == "POST":
        data = json.loads(request.body)
        grade_id = data.get('grade')
        # 判断grade_id是否存在
        if not grade_id:
            return JsonResponse({'status':'error','messages':'班级参数缺失'}, status=400)
        
        # 判断班级是否存在
        try:
            grade = Grade.objects.get(id=grade_id)
        except Grade.DoesNotExist:
            return JsonResponse({'status':'error','messages':'班级不存在'}, status=404)
        
        # 从数据库查询成绩信息
        scores = Score.objects.filter(grade=grade)
        if not scores.exists():
            return JsonResponse({'status':'error', 'messages':'找不到指定班级的学生信息'}, status=404)
        
        # 操作excel
        wb = openpyxl.Workbook()
        ws = wb.active
        # ws.title = f"{grade.grade_name}成绩单"
        # 添加表头
        columns = ['考试名称','姓名','班级','学号','语文','数学','英语']
        ws.append(columns)

        for score in scores:
            ws.append([score.title, score.student_name, score.grade.grade_name, score.student_number, score.chinese_score, score.math_score, score.english_score])

        # 将excel数据保存到内存中
        excel_file = BytesIO()
        wb.save(excel_file)
        wb.close()

        # 
        excel_file.seek(0)

        filename = f"{grade.grade_name}成绩单.xlsx"
        # 对文件名进行URL编码，确保特殊字符正确处理
        # encoded_filename = escape_uri_path(filename)

        # 
        response = HttpResponse(excel_file.read(), content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
        response['Content-Disposition'] = f'attachment; filename="{filename}"'
        return response

class ScoresDetailView(BasecoreView, DetailView):
    template_name = 'scores/score_detail.html'


class MyScoreListView(BasecoreView, ListView):
    template_name = 'scores/my_score_list.html'
    paginate_by = 10

    def get_queryset(self):
        student_number = self.request.user.student.student_number
        return Score.objects.filter(student_number=student_number)

